
#ifdef _M_X64
#define X86_64
#else // _M_IX86
#define X86
#endif

#ifdef _MSC_VER
// C4201: "nonstandard extension used : nameless struct/union"
// C4214: "nonstandard extension used : bit field types other than int"
#pragma warning(disable : 4214 4201)
#define uint64_t UINT64
#define uint32_t UINT32
#define uint16_t UINT16
#define uint8_t UINT8
#endif

#ifndef _MSC_VER
#ifdef X86_64
#warning X86_64
#else
#warning X86
#endif
#endif

#ifndef _MSC_VER
#define packed_data __attribute__ ((__packed__))
#else
#define packed_data
#pragma pack(push, 1)
#endif

// Fig. 3-8: Segment Descriptor, p. 1730
struct packed_data segment_descriptor_t
{
	// low word
	uint16_t segment_limit_0015;
	uint16_t base_address_0015;
	// high word
	uint16_t base_address_1623 : 7;
	uint8_t segment_type : 4;
	uint8_t descriptor_type : 1;
	uint8_t privilege_level : 2;
	uint8_t segment_present : 1;
	uint8_t segment_limit_1619 : 4;
	uint8_t avl : 1;
	uint8_t sixtyfour_code_segment : 1;
	uint8_t default_operation_size : 1;
	uint8_t granularity : 1;
	uint8_t base_2431 : 8;
};
typedef struct segment_descriptor_t segment_descriptor_t;

union packed_data segment_selector_t
{
	uint16_t selector;
	struct packed_data {
		uint8_t rpl : 2;
		uint8_t table : 1;
		uint16_t index : 13;
	};
};

struct packed_data segment_register_t
{
	// "hidden" part / "shadow register"
	segment_descriptor_t descriptor;
	// "visible" part
	union segment_selector_t selector;
};
typedef struct segment_register_t segment_register_t;

// Fig. 2-6: Memory Management Registers, p. 1708
#ifndef X86_64
#define systable_base_t uint32_t
#else   // when X86_64
#define systable_base_t uint64_t
#endif
struct packed_data system_table_register_t
{
	uint16_t limit;
	systable_base_t base;
};
typedef struct system_table_register_t system_table_register_t;

#ifdef _MSC_VER
#pragma pack(pop)
#endif

#ifdef _MSC_VER
#undef uint64_t
#undef uint32_t
#undef uint16_t
#undef uint8_t
#endif
